import sys
from PyQt4.QtCore import SIGNAL, QObject, QTimer
from PyQt4.QtGui import *
from client import MPD

class QMPD(QObject):
    def __init__(self):
        QObject.__init__(self)
        self._client = MPD()
        self._status = None
        self._playlist_id = -1
        self._playlist = []
        self._current_song_id = -1
        self._current_song = {}
        self._inhibit = 0
        self._force_cached = False
        self._update_commands = dict((k,k) for k in [ 'load',
                                                     'shuffle',
                                                     'move',
                                                     'setvol',
                                                     'kill',
                                                     'previous',
                                                     'pause',
                                                     'next',
                                                     'add',
                                                     'swap',
                                                     'plchangesposid',
                                                     'seekid',
                                                     'random',
                                                     'playlistadd',
                                                     'stop',
                                                     'volume',
                                                     'playlistclear',
                                                     'playlistmodel',
                                                     'clearerror',
                                                     'delete',
                                                     'rename',
                                                     'playid',
                                                     'close',
                                                     'seek',
                                                     'enableoutput',
                                                     'rm',
                                                     'play',
                                                     'repeat',
                                                     'swapid',
                                                     'addid',
                                                     'playlistdelete',
                                                     'disableoutput',
                                                     'clear',
                                                     'moveid',
                                                     'deleteid' ])

        self.timer = QTimer()
        self.connect(self.timer, SIGNAL("timeout()"), self._tick)
        self.timer.setInterval(1000)
        self.timer.start()

    def mpd_connect(self, server, port, password):
        self._server = server
        self._port = port
        self._password = password
        self._client.set_server(server, port, password)
        self._tick()

    def emit(self, *args, **kwargs):
        if self._inhibit < 1:
            QObject.emit(self,*args,**kwargs)

    def _tick(self):
        try:
            self._force_cached = True
            if self._client.state == self._client.initial_state:
                return

            self._status = self._client.status()

            if self._status:
                playlist_id = self._status.get('playlist', -1)
                if playlist_id != self._playlist_id:
                    self._playlist = self._client.playlistinfo()
                    self._playlist_id = playlist_id
                    self.emit(SIGNAL('playlist()'))

                current_song_id = self._status.get('song',-1)
                if current_song_id != self._current_song_id:
                    self._current_song = self._client.currentsong()
                    self._current_song_id = current_song_id
                    self.emit(SIGNAL('currentsong()'))

                self.emit(SIGNAL('status()'))
        finally:
            self._force_cached = False

    def __getattr__(self,attr):
        tmp = getattr(self._client, attr)
        if (attr in self._update_commands):
            return lambda *args,**kwargs: self._call_then_update(tmp, *args,**kwargs)
        return tmp

    def _call_then_update(self, fn, *args, **kwargs):
        res = fn(*args, **kwargs)
        self._tick()
        return res

    def status(self):
        if self._status or self._force_cached:
            return self._status
        else:
            self.inhibit_signals(self._tick)
            return self._status

    def currentsong(self):
        if self._current_song or self._force_cached:
            return self._current_song
        else:
            self.inhibit_signals(self._tick)
            return self._current_song

    def playlistinfo(self):
        if self._playlist or self._force_cached:
            return self._playlist
        else:
            self.inhibit_signals(self._tick)
            return self._playlist

    def inhibit_signals(self,call,*args,**kwargs):
        try:
            self._inhibit += 1
            call(*args,**kwargs)
        finally:
            self._inhibit -= 1


class UI(QMainWindow):
    def __init__(self,parent=None):
        QMainWindow.__init__(self,parent)
        l = QHBoxLayout()
        b = QPushButton("Push me", self)
        self.connect(b, SIGNAL("clicked()"), self.click)
        l.addWidget(b)
        self.setLayout(l)
        self.qmpd = QMPD()
        self.connect(self, SIGNAL("status()"), self.cb)
        self.qmpd.mpd_connect("medea",6600)
        self.connect(self.qmpd, SIGNAL("playlist()"), lambda: self.cb("PLAYLIST"))
        self.connect(self.qmpd, SIGNAL("status()"), lambda: self.cb("STATUS"))
        self.connect(self.qmpd, SIGNAL("currentsong()"), lambda: self.cb("CURRENTSONG"))

    def click(self):
        self.qmpd.stop()

    def cb(self,m):
        print m



if __name__ == "__main__":
    app = QApplication(sys.argv)
    myapp = UI()
    myapp.show()
    sys.exit(app.exec_())
